package imai78gae.heya.guice;

import imai78gae.heya.action.EntranceAction;
import imai78gae.heya.action.GroupAction;
import imai78gae.heya.action.IndexAction;
import imai78gae.heya.action.NewAccountAction;
import imai78gae.heya.action.NewGroupAction;
import imai78gae.heya.service.AccountService;
import imai78gae.heya.service.GroupService;
import imai78gae.heya.service.impl.AccountServiceImpl;
import imai78gae.heya.service.impl.GroupServiceImpl;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.seasar.cubby.action.FlashMap;
import org.seasar.cubby.action.impl.FlashMapImpl;
import org.seasar.cubby.fileupload.StreamFileItemFactory;
import org.seasar.cubby.plugins.guice.CubbyModule;
import org.seasar.cubby.plugins.guice.FileUploadModule;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.ServletModule;
import com.google.inject.util.Modules;

/**
 * {@code Guice}を使った{@code DI}を行う為のクラスです。
 * 
 * @author imai78
 *
 */
public class HeyaModule extends AbstractModule {

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void configure() {
		// Servlet binding
		super.install(new ServletModule());
		super.install(Modules.override(new CubbyModule(), new FileUploadModule())
				.with(new MyCubbyModule()));
		// Service binding
		super.bind(AccountService.class).to(AccountServiceImpl.class).in(Scopes.NO_SCOPE);
		super.bind(GroupService.class).to(GroupServiceImpl.class).in(Scopes.NO_SCOPE);
		// Cubby action binding
		super.bind(IndexAction.class);		// トップ画面用Action
		super.bind(NewAccountAction.class);	// 新規アカウントの作成画面用Action
		super.bind(EntranceAction.class);	// ログイン後のエントランス画面用Action
		super.bind(NewGroupAction.class);	// 新規グループの作成画面用Action
		super.bind(GroupAction.class);		// ルーム画面用Action
	}

	/**
	 * TODO これがないと{@code Cubby}が動かない。。。なんで？
	 * 
	 * @author imai78
	 *
	 */
	public static class MyCubbyModule extends AbstractModule {

		/**
		 * {@inheritDoc}
		 */
		@Override
		protected void configure() {
			;
		}

		/**
		 * FileUpload機能を提供します。
		 * 
		 * @return
		 */
		@Provides
		FileUpload provideFileUpload() {
			final FileItemFactory fileItemFactory = new StreamFileItemFactory();
			final FileUpload fileUpload = new ServletFileUpload(fileItemFactory);
			return fileUpload;
		}

		/**
		 * {@code FlashMap}機能を提供します。
		 * 
		 * @param request
		 * @return
		 */
		@Provides
		@RequestScoped
		FlashMap provideFlashMap(final HttpServletRequest request) {
			return new FlashMapImpl(request) {
				/**
				 * {@link Map}を生成して返します。
				 */
				@Override
				protected Map<String, Object> createMap() {
					return new HashMap<String, Object>();
				}
			};
		}
	}

}
